/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-09-18 10:20:00
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-09-18 10:20:00
 * @FilePath: /go-helper/utils/id.go
 * @Description: ID生成工具函数，支持UUID、雪花ID、短ID等多种ID生成方式
 */

package ixUtils

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"math/big"
	"net"
	"strconv"
	"sync"
	"time"
)

// ========== UUID生成 ==========

// GenerateUUID 生成标准UUID (RFC 4122 Version 4)
func GenerateUUID() string {
	return GenerateUUIDv4()
}

// GenerateUUIDv4 生成UUID Version 4 (随机)
func GenerateUUIDv4() string {
	// 生成16字节随机数据
	bytes := make([]byte, 16)
	_, err := rand.Read(bytes)
	if err != nil {
		// 如果随机数生成失败，使用时间戳作为fallback
		return generateTimeBasedUUID()
	}

	// 设置版本号 (4) 和变体
	bytes[6] = (bytes[6] & 0x0f) | 0x40 // Version 4
	bytes[8] = (bytes[8] & 0x3f) | 0x80 // Variant 10

	// 格式化为标准UUID字符串
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		bytes[0:4], bytes[4:6], bytes[6:8], bytes[8:10], bytes[10:16])
}

// GenerateUUIDv1 生成UUID Version 1 (基于时间和MAC地址)
func GenerateUUIDv1() string {
	// 获取当前时间戳 (100纳秒为单位，从1582年开始)
	now := time.Now()
	timestamp := uint64(now.UnixNano()/100) + 0x01B21DD213814000

	// 获取MAC地址
	macAddr := getMACAddress()
	if macAddr == nil {
		// 如果无法获取MAC地址，生成随机节点ID
		macAddr = make([]byte, 6)
		rand.Read(macAddr)
		macAddr[0] |= 0x01 // 设置多播位
	}

	// 生成时钟序列
	clockSeq := uint16(now.Nanosecond() & 0x3fff)

	// 构建UUID
	timeLow := uint32(timestamp & 0xffffffff)
	timeMid := uint16((timestamp >> 32) & 0xffff)
	timeHi := uint16((timestamp>>48)&0x0fff) | 0x1000 // Version 1

	return fmt.Sprintf("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
		timeLow, timeMid, timeHi,
		(clockSeq&0x3fff)|0x8000, // Variant 10
		macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5])
}

// GenerateSimpleUUID 生成简单UUID (无连字符)
func GenerateSimpleUUID() string {
	uuid := GenerateUUIDv4()
	return uuid[0:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
}

// GenerateShortUUID 生成短UUID (22字符)
func GenerateShortUUID() string {
	bytes := make([]byte, 16)
	rand.Read(bytes)

	// 使用base62编码生成更短的字符串
	return base62Encode(bytes)[:22]
}

// ========== 雪花ID (Snowflake) ==========

// SnowflakeGenerator 雪花ID生成器
type SnowflakeGenerator struct {
	mutex         sync.Mutex
	epoch         int64 // 起始时间戳 (毫秒)
	workerID      int64 // 工作机器ID
	datacenterID  int64 // 数据中心ID
	sequence      int64 // 序列号
	lastTimestamp int64 // 上次生成ID的时间戳
}

// 雪花ID各部分的位数
const (
	workerIDBits     = 5  // 工作机器ID位数
	datacenterIDBits = 5  // 数据中心ID位数
	sequenceBits     = 12 // 序列号位数

	maxWorkerID     = -1 ^ (-1 << workerIDBits)     // 最大工作机器ID
	maxDatacenterID = -1 ^ (-1 << datacenterIDBits) // 最大数据中心ID
	maxSequence     = -1 ^ (-1 << sequenceBits)     // 最大序列号

	workerIDShift      = sequenceBits                                   // 工作机器ID左移位数
	datacenterIDShift  = sequenceBits + workerIDBits                    // 数据中心ID左移位数
	timestampLeftShift = sequenceBits + workerIDBits + datacenterIDBits // 时间戳左移位数
)

// 默认起始时间 (2020-01-01 00:00:00 UTC)
var defaultEpoch int64 = 1577836800000

// 全局雪花ID生成器
var globalSnowflake *SnowflakeGenerator
var snowflakeOnce sync.Once

// NewSnowflakeGenerator 创建雪花ID生成器
func NewSnowflakeGenerator(workerID, datacenterID int64) (*SnowflakeGenerator, error) {
	if workerID < 0 || workerID > maxWorkerID {
		return nil, fmt.Errorf("工作机器ID必须在0-%d之间", maxWorkerID)
	}
	if datacenterID < 0 || datacenterID > maxDatacenterID {
		return nil, fmt.Errorf("数据中心ID必须在0-%d之间", maxDatacenterID)
	}

	return &SnowflakeGenerator{
		epoch:        defaultEpoch,
		workerID:     workerID,
		datacenterID: datacenterID,
		sequence:     0,
	}, nil
}

// Generate 生成雪花ID
func (s *SnowflakeGenerator) Generate() int64 {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	timestamp := time.Now().UnixNano() / 1e6 // 毫秒时间戳

	if timestamp < s.lastTimestamp {
		// 时钟回拨，等待到下一毫秒
		timestamp = s.waitNextMillis(s.lastTimestamp)
	}

	if timestamp == s.lastTimestamp {
		// 同一毫秒内，序列号递增
		s.sequence = (s.sequence + 1) & maxSequence
		if s.sequence == 0 {
			// 序列号溢出，等待下一毫秒
			timestamp = s.waitNextMillis(s.lastTimestamp)
		}
	} else {
		// 不同毫秒，序列号重置
		s.sequence = 0
	}

	s.lastTimestamp = timestamp

	// 生成ID
	return ((timestamp - s.epoch) << timestampLeftShift) |
		(s.datacenterID << datacenterIDShift) |
		(s.workerID << workerIDShift) |
		s.sequence
}

// waitNextMillis 等待到下一毫秒
func (s *SnowflakeGenerator) waitNextMillis(lastTimestamp int64) int64 {
	timestamp := time.Now().UnixNano() / 1e6
	for timestamp <= lastTimestamp {
		time.Sleep(time.Millisecond)
		timestamp = time.Now().UnixNano() / 1e6
	}
	return timestamp
}

// GenerateSnowflakeID 生成雪花ID (使用全局生成器)
func GenerateSnowflakeID() int64 {
	snowflakeOnce.Do(func() {
		// 自动获取工作机器ID和数据中心ID
		workerID := getWorkerID()
		datacenterID := getDatacenterID()

		var err error
		globalSnowflake, err = NewSnowflakeGenerator(workerID, datacenterID)
		if err != nil {
			// 如果创建失败，使用默认值
			globalSnowflake, _ = NewSnowflakeGenerator(1, 1)
		}
	})

	return globalSnowflake.Generate()
}

// ParseSnowflakeID 解析雪花ID
func ParseSnowflakeID(id int64) map[string]int64 {
	timestamp := (id >> timestampLeftShift) + defaultEpoch
	datacenterID := (id >> datacenterIDShift) & maxDatacenterID
	workerID := (id >> workerIDShift) & maxWorkerID
	sequence := id & maxSequence

	return map[string]int64{
		"timestamp":    timestamp,
		"datacenterID": datacenterID,
		"workerID":     workerID,
		"sequence":     sequence,
		"time":         timestamp, // 兼容字段
	}
}

// ========== 短ID生成 ==========

// GenerateShortID 生成短ID (8-12字符)
func GenerateShortID() string {
	return GenerateShortIDWithLength(8)
}

// GenerateShortIDWithLength 生成指定长度的短ID
func GenerateShortIDWithLength(length int) string {
	if length <= 0 {
		length = 8
	}

	// 使用时间戳 + 随机数生成
	timestamp := time.Now().UnixNano()
	random, _ := rand.Int(rand.Reader, big.NewInt(1000000))

	combined := fmt.Sprintf("%d%d", timestamp, random.Int64())
	hash := simpleHash(combined)

	return base62Encode([]byte(hash))[:length]
}

// GenerateNanoID 生成NanoID风格的ID
func GenerateNanoID(size int) string {
	if size <= 0 {
		size = 21 // NanoID默认长度
	}

	// NanoID字符集
	alphabet := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-"
	result := make([]byte, size)

	for i := 0; i < size; i++ {
		randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(alphabet))))
		result[i] = alphabet[randomIndex.Int64()]
	}

	return string(result)
}

// ========== ObjectID生成 (MongoDB风格) ==========

// ObjectIDGenerator ObjectID生成器
type ObjectIDGenerator struct {
	counter uint32
	mutex   sync.Mutex
}

var globalObjectIDGenerator = &ObjectIDGenerator{}

// GenerateObjectID 生成ObjectID (MongoDB风格)
func GenerateObjectID() string {
	return globalObjectIDGenerator.Generate()
}

// Generate 生成ObjectID
func (g *ObjectIDGenerator) Generate() string {
	g.mutex.Lock()
	g.counter++
	counter := g.counter
	g.mutex.Unlock()

	// ObjectID = 4字节时间戳 + 5字节随机值 + 3字节递增计数器
	timestamp := uint32(time.Now().Unix())

	// 生成5字节随机值
	randomBytes := make([]byte, 5)
	rand.Read(randomBytes)

	// 3字节计数器
	counterBytes := []byte{
		byte(counter >> 16),
		byte(counter >> 8),
		byte(counter),
	}

	// 组合成12字节
	objectID := make([]byte, 12)

	// 时间戳 (4字节，大端序)
	objectID[0] = byte(timestamp >> 24)
	objectID[1] = byte(timestamp >> 16)
	objectID[2] = byte(timestamp >> 8)
	objectID[3] = byte(timestamp)

	// 随机值 (5字节)
	copy(objectID[4:9], randomBytes)

	// 计数器 (3字节)
	copy(objectID[9:12], counterBytes)

	return hex.EncodeToString(objectID)
}

// ParseObjectID 解析ObjectID
func ParseObjectID(objectID string) (map[string]interface{}, error) {
	if len(objectID) != 24 {
		return nil, fmt.Errorf("ObjectID长度必须是24个字符")
	}

	bytes, err := hex.DecodeString(objectID)
	if err != nil {
		return nil, fmt.Errorf("ObjectID格式错误: %v", err)
	}

	// 解析时间戳
	timestamp := uint32(bytes[0])<<24 | uint32(bytes[1])<<16 | uint32(bytes[2])<<8 | uint32(bytes[3])
	createTime := time.Unix(int64(timestamp), 0)

	// 解析计数器
	counter := uint32(bytes[9])<<16 | uint32(bytes[10])<<8 | uint32(bytes[11])

	return map[string]interface{}{
		"timestamp":  timestamp,
		"createTime": createTime,
		"counter":    counter,
		"randomPart": hex.EncodeToString(bytes[4:9]),
	}, nil
}

// ========== 其他ID生成工具 ==========

// GenerateOrderID 生成订单ID (时间戳+随机数)
func GenerateOrderID() string {
	now := time.Now()
	timestamp := now.Format("20060102150405")
	random := generateRandomDigits(6)
	return timestamp + random
}

// GenerateTraceID 生成链路追踪ID
func GenerateTraceID() string {
	return GenerateNanoID(32)
}

// GenerateSpanID 生成Span ID
func GenerateSpanID() string {
	return GenerateNanoID(16)
}

// GenerateRequestID 生成请求ID
func GenerateRequestID() string {
	return GenerateNanoID(16)
}

// GenerateSessionID 生成会话ID
func GenerateSessionID() string {
	return GenerateNanoID(32)
}

// GenerateAPIKey 生成API密钥
func GenerateAPIKey() string {
	prefix := "ak_"
	id := GenerateNanoID(32)
	return prefix + id
}

// GenerateSecretKey 生成密钥
func GenerateSecretKey() string {
	prefix := "sk_"
	id := GenerateNanoID(48)
	return prefix + id
}

// ========== 工具函数 ==========

// ValidateUUID 验证UUID格式
func ValidateUUID(uuid string) bool {
	if len(uuid) != 36 {
		return false
	}

	// 检查连字符位置
	if uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-' {
		return false
	}

	// 检查每个部分是否为十六进制
	parts := []string{
		uuid[0:8], uuid[9:13], uuid[14:18], uuid[19:23], uuid[24:36],
	}

	for _, part := range parts {
		for _, char := range part {
			if !((char >= '0' && char <= '9') ||
				(char >= 'a' && char <= 'f') ||
				(char >= 'A' && char <= 'F')) {
				return false
			}
		}
	}

	return true
}

// ValidateObjectID 验证ObjectID格式
func ValidateObjectID(objectID string) bool {
	if len(objectID) != 24 {
		return false
	}

	for _, char := range objectID {
		if !((char >= '0' && char <= '9') ||
			(char >= 'a' && char <= 'f') ||
			(char >= 'A' && char <= 'F')) {
			return false
		}
	}

	return true
}

// ========== 内部辅助函数 ==========

// getMACAddress 获取MAC地址
func getMACAddress() []byte {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil
	}

	for _, iface := range interfaces {
		if len(iface.HardwareAddr) >= 6 {
			return iface.HardwareAddr[:6]
		}
	}

	return nil
}

// getWorkerID 获取工作机器ID
func getWorkerID() int64 {
	// 基于MAC地址生成工作机器ID
	macAddr := getMACAddress()
	if macAddr != nil {
		return int64(macAddr[len(macAddr)-1]) & maxWorkerID
	}

	// 如果无法获取MAC地址，使用随机数
	random, _ := rand.Int(rand.Reader, big.NewInt(maxWorkerID+1))
	return random.Int64()
}

// getDatacenterID 获取数据中心ID
func getDatacenterID() int64 {
	// 基于主机名或其他标识生成数据中心ID
	// 这里使用简单的随机数，实际使用时可以根据部署环境配置
	random, _ := rand.Int(rand.Reader, big.NewInt(maxDatacenterID+1))
	return random.Int64()
}

// base62Encode Base62编码
func base62Encode(data []byte) string {
	alphabet := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

	// 将字节数组转换为大整数
	num := big.NewInt(0)
	num.SetBytes(data)

	if num.Cmp(big.NewInt(0)) == 0 {
		return string(alphabet[0])
	}

	result := ""
	base := big.NewInt(62)
	zero := big.NewInt(0)

	for num.Cmp(zero) > 0 {
		mod := big.NewInt(0)
		num.DivMod(num, base, mod)
		result = string(alphabet[mod.Int64()]) + result
	}

	return result
}

// simpleHash 简单哈希函数
func simpleHash(s string) string {
	hash := uint32(0)
	for _, char := range s {
		hash = hash*31 + uint32(char)
	}
	return strconv.FormatUint(uint64(hash), 16)
}

// generateTimeBasedUUID 基于时间生成UUID (fallback)
func generateTimeBasedUUID() string {
	now := time.Now()
	timestamp := now.UnixNano()

	// 使用时间戳生成UUID
	return fmt.Sprintf("%08x-%04x-4%03x-%04x-%012x",
		uint32(timestamp&0xffffffff),
		uint16((timestamp>>32)&0xffff),
		uint16((timestamp>>48)&0x0fff),
		uint16(now.Nanosecond()&0x3fff)|0x8000,
		uint64(now.UnixNano())&0xffffffffffff)
}

// generateRandomDigits 生成指定长度的随机数字字符串
func generateRandomDigits(length int) string {
	digits := "0123456789"
	result := make([]byte, length)

	for i := 0; i < length; i++ {
		randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(digits))))
		result[i] = digits[randomIndex.Int64()]
	}

	return string(result)
}
